﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using Rhino.Mocks;
using Rhino.Mocks.Interfaces;
using Rhino.Mocks.Constraints;

using SharedGenomics.Workbench.Core;
using SharedGenomics.Workbench.Presenters;
using SharedGenomics.Annotations;
using SharedGenomics.Workbench.Views;
using SharedGenomics.Workbench.Services;
using SharedGenomics.Workbench.Tests.TestObjects;

namespace SharedGenomics.Workbench.Tests.Presenters
{
    [TestClass]
    public class AnnotationWrapperPresenterTests
    {
        private Rhino.Mocks.MockRepository mocks = new Rhino.Mocks.MockRepository();
        private IAnnotationNotifier notifier;
        private IAnnotationWrapperView view;

        [TestInitialize]
        public void Setup()
        {
            this.notifier = this.mocks.Stub<IAnnotationNotifier>();
            this.view = this.mocks.DynamicMock<IAnnotationWrapperView>();
        }

        [TestMethod]
        public void ShouldCaptureAnnotationOnShown()
        {
            this.notifier = this.mocks.StrictMock<IAnnotationNotifier>();
            IEventRaiser shownEvent;
            IAnnotationPresenter wrappedPresenter = this.mocks.Stub<IAnnotationPresenter>();

            using (this.mocks.Record())
            {
                IAnnotation a = this.mocks.Stub<IAnnotation>();
                var viewImg = new System.Drawing.Bitmap(200, 200);

                shownEvent = this.view.Stub(v => v.Shown += null).IgnoreArguments().GetEventRaiser();
                wrappedPresenter.Stub(p => p.SnapshotOnOpen).Return(true);
                wrappedPresenter.Stub(p => p.Annotation).Return(a);
                wrappedPresenter.Stub(p => p.View).Return(new StubView());

                view.Stub(v => v.GetViewImage()).Return(viewImg);

                this.notifier.Expect(n => n.CaptureAnnotation(Guid.Empty, null, null)).IgnoreArguments().Constraints(
                    Is.NotEqual(Guid.Empty),
                    Is.Same(a),
                    Is.Same(viewImg));
            }

            using (this.mocks.Playback())
            {
                var presenter = this.CreatePresenter();
                presenter.WrappedPresenter = wrappedPresenter;

                shownEvent.Raise(null, null);
            }
        }

        [TestMethod]
        public void ShouldNotCaptureOnShown()
        {
            this.notifier = MockRepository.GenerateMock<IAnnotationNotifier>();
            IEventRaiser shownEvent;
            IPresenter wrappedPresenter = MockRepository.GenerateStub<IPresenter>();

            shownEvent = this.view.Stub(v => v.Shown += null).IgnoreArguments().GetEventRaiser();
            wrappedPresenter.Stub(p => p.View).Return(new StubView());

            var presenter = this.CreatePresenter();
            presenter.WrappedPresenter = wrappedPresenter;

            shownEvent.Raise(null, null);
        }

        [TestMethod]
        public void ShouldNotifyImportanceChanged()
        {
            this.notifier = this.mocks.StrictMock<IAnnotationNotifier>();
            IEventRaiser importanceChangedEvent;
            Guid viewId = Guid.NewGuid();

            using (this.mocks.Record())
            {
                importanceChangedEvent = this.view.Stub(v => v.ImportanceChanged += null).IgnoreArguments().GetEventRaiser();
                this.view.Stub(v => v.IsImportant).Return(true);

                this.notifier.Expect(n => n.SetAnnotationImportance(viewId, true));
            }

            using (this.mocks.Playback())
            {
                var presenter = this.CreatePresenter();
                presenter.AnnotationViewId = viewId;
                importanceChangedEvent.Raise(null, null);
            }
        }

        private MockWrapperPresenter CreatePresenter()
        {
            return new MockWrapperPresenter(this.view, this.notifier);
        }

        #region MockWrapperPresenter

        private class MockWrapperPresenter : AnnotationWrapperPresenter
        {
            public MockWrapperPresenter(IAnnotationWrapperView view, IAnnotationNotifier notifier)
                : base(view, notifier)
            { }

            public Guid AnnotationViewId
            {
                set { this.AnnotationId = value; }
            }
        }

        #endregion
    }
}